<?php
/**
 * Created by PhpStorm.
 * User: ari
 * Date: 12/3/14
 * Time: 4:37 PM
 */
namespace BC\User;

use BC\PGP\Commands\PGPExportPublicKeyCommand;
use BC\PGP\Commands\PGPSearchCommand;
use BC\PGP\PGPConfig;
use BC\SiteIndex;
use CPath\Build\IBuildable;
use CPath\Build\IBuildRequest;
use CPath\Data\Map\IKeyMap;
use CPath\Data\Map\IKeyMapper;
use CPath\Render\HTML\Attribute\Attributes;
use CPath\Render\HTML\Element\Form\HTMLForm;
use CPath\Render\HTML\Element\Form\HTMLInputField;
use CPath\Render\HTML\Element\Form\HTMLTextAreaField;
use CPath\Render\HTML\Element\HTMLElement;
use CPath\Render\HTML\Header\HTMLMetaTag;
use CPath\Request\IRequest;
use CPath\Request\Validation\RequiredValidation;
use CPath\Response\IResponse;
use CPath\Route\IRoutable;
use CPath\Route\RouteBuilder;

class KeyRoute implements IRoutable, IBuildable, IKeyMap
{
	const PATH_FORMAT = '/key/%s';
	const PATH_FORMAT2 = '/user/%s/key';

	const FORM_ACTION = 'key';
	const CLS_FORM = 'form-key';

	const CLS_FIELD_FINGERPRINT = 'field-fingerprint';
	const CLS_FIELD_PUBLIC_KEY = 'field-public-key';

	const CLS_FIELD_SUBMIT = 'field-submit';

	const CLS_FIELDSET_SUBMIT = 'fieldset-submit';


	const PARAM_FINGERPRINT = 'fingerprint';
	const PARAM_SUBMIT = 'submit';

	/** @var PGPSearchCommand */
	private $mSearch;
	private $mFingerprint;

	private $pForm;
	/** @var HTMLTextAreaField */
	private $pPublicKey;

	public function __construct($fingerprint) {
//		$this->mSearch = new PGPSearchCommand($keySearch, '');
//		$this->mSearch->setPrimaryKeyRing(PGPConfig::$KEYRING_USER);
//		$this->mSearch->addKeyRing(PGPConfig::$KEYRING_GRANT);
//		$this->mSearch = $this->mSearch->queryOne();
		$this->mFingerprint = $fingerprint;

		$action = sprintf(self::PATH_FORMAT2, $this->mFingerprint);
		$this->pForm = new HTMLForm('POST', $action, self::CLS_FORM,

			new HTMLMetaTag(HTMLMetaTag::META_TITLE, 'User Public Key - ' . $this->mSearch->getUserID()),
			//new HTMLHeaderScript(__DIR__ . '\assets\form-' . self::FORM_ACTION . '.js'),
			//new HTMLHeaderStyleSheet(__DIR__ . '\assets\form-' . self::FORM_ACTION . '.css'),

			new HTMLElement('legend', 'content-title', 'Public Key - ' . $this->mSearch->getUserID()),

			new HTMLElement('fieldset', self::CLS_FIELD_PUBLIC_KEY,
				new HTMLElement('legend', 'legend-public-key toggle', "Public Key"),

				$this->pPublicKey = new HTMLTextAreaField('challenge', new Attributes('readonly', 'readonly')
				)
			)
//
		);
	}

	public function getFingerprint() {
		return $this->mFingerprint;
	}

	public function getSearch() {
		return $this->mSearch;
	}

	function exportPublicKey(IRequest $Request=null) {
		$PGPExport = new PGPExportPublicKeyCommand($this->getFingerprint());
		$PGPExport->setPrimaryKeyRing(PGPConfig::$KEYRING_USER);
		$PGPExport->addKeyRing(PGPConfig::$KEYRING_GRANT);
		$PGPExport->execute($Request);
		return $PGPExport->getExportedString();
	}

	/**
	 * Execute a command and return a response. Does not render
	 * @param IRequest $Request
	 * @return IResponse the execution response
	 */
	function execute(IRequest $Request) {
		$publicKeyString = $this->exportPublicKey($Request);
		$this->pPublicKey->setInputValue($publicKeyString);
		return $this->pForm;
	}

	/**
	 * Map data to the key map
	 * @param IKeyMapper $Map the map inst to add data to
	 * @internal param \CPath\Request\IRequest $Request
	 * @internal param \CPath\Request\IRequest $Request
	 * @return void
	 */
	function mapKeys(IKeyMapper $Map) {
		$Map->map('fingerprint', $this->getFingerprint());
		$publicKeyString = $this->exportPublicKey();
		$Map->map('public_key', $publicKeyString);
		$Map->map('search', $this->getSearch());
	}

	// Static

	/**
	 * Route the request to this class object and return the object
	 * @param IRequest $Request the IRequest inst for this render
	 * @param array|null $Previous all previous response object that were passed from a handler, if any
	 * @param null|mixed $_arg [varargs] passed by route map
	 * @throws \CPath\Request\Exceptions\RequestException
	 * @return void|bool|Object returns a response object
	 * If nothing is returned (or bool[true]), it is assumed that rendering has occurred and the request ends
	 * If false is returned, this static handler will be called again if another handler returns an object
	 * If an object is returned, it is passed along to the next handler
	 */
	static function routeRequestStatic(IRequest $Request, Array &$Previous = array(), $_arg = null) {
		$FingerprintField = new HTMLInputField(self::PARAM_FINGERPRINT, function (IRequest $Request, $value) {
//				if (!$value && $Request instanceof ISessionRequest)
//					$value = UserSession::getUserFingerprintFromSession($Request);

				return $value;
			}, new RequiredValidation()
		);
		$userFingerprint = $FingerprintField->validate($Request);
		return new KeyRoute($userFingerprint);
	}


	/**
	 * Handle this request and render any content
	 * @param IBuildRequest $Request the build request inst for this build session
	 * @return void
	 * @build --disable 0
	 * Note: Use doctag 'build' with '--disable 1' to have this IBuildable class skipped during a build
	 */
	static function handleBuildStatic(IBuildRequest $Request) {
		$RouteBuilder = new RouteBuilder($Request, new SiteIndex());
//		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT, ':' . self::PARAM_FINGERPRINT), __CLASS__);
		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT, ''), __CLASS__);
		$RouteBuilder->writeRoute('ANY ' . sprintf(self::PATH_FORMAT2, ':' . self::PARAM_FINGERPRINT), __CLASS__);
	}
}